package com.smi.cn.satemachine;

import com.smi.cn.satemachine.ReturnVo.RmaStatus;
import com.smi.cn.satemachine.ReturnVo.RmaTrigger;
import com.smi.cn.satemachine.ReturnVo.RmaType;
import com.smi.cn.satemachine.annotation.PersistModule;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.GenericTypeResolver;
import org.squirrelframework.foundation.fsm.StateMachineBuilderFactory;
import org.squirrelframework.foundation.fsm.StateMachineConfiguration;
import org.squirrelframework.foundation.fsm.UntypedStateMachine;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;

/**
 * Created by zhangyanfei on 2017/7/25.
 *
 * @author zhangyanfei
 * @date 2017/07/25
 */
public abstract class AbstractStatemachineEngine<T extends UntypedStateMachine> implements ApplicationContextAware{
    protected UntypedStateMachineBuilder stateMachineBuilder = null;
    protected ApplicationContext applicationContext = null;

    /**
     * set 注入
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public AbstractStatemachineEngine(){
        //获取泛型参数
        Class<T> genericType= (Class<T>)GenericTypeResolver.resolveTypeArgument(getClass(),AbstractStatemachineEngine.class);
        /**
         * 获取machine的builder
         * 第一个是状态机class  第二个是状态机构造函数的入参
         */
        stateMachineBuilder = StateMachineBuilderFactory.create(genericType, ApplicationContext.class);

    }

    /**
     * 修改状态
     */
    public ReturnVo fire(ReturnVo returnVo, RmaTrigger rmaTrigger,StateMachineContext context){
        try{
            T stateMachine = stateMachineBuilder.newUntypedStateMachine(RmaStatus.getStatus(returnVo.getStatus()),
                    StateMachineConfiguration.create().enableDebugMode(true).enableAutoStart(true), applicationContext);
            stateMachine.addDeclarativeListener(applicationContext.getBean(PersistModule.class));
            stateMachine.fire(rmaTrigger,context);
        }catch (Exception e){
            throw e;
        }
        return returnVo;
    }

    public abstract boolean accept(RmaType rmaType);

}
